
#ifndef _SERVICE_COMMON_THREAD_POOL_H
#define _SERVICE_COMMON_THREAD_POOL_H
//This file should not be include directly,
//please include Service/Common/TaskProcessor.h or Agent/Common/TaskScheduler.h

#include <list>
#include <string>

#include "Utility/ErrorCode.h"
#include "Utility/Event.h"
#include "Utility/Mutex.h"
#include "Utility/Thread.h"

namespace nebula { namespace utility {

class ThreadPool
{
protected:
	enum ThreadStatus
	{
		THR_STATUS_IDLE = 0,
		THR_STATUS_BUSY,
		THR_STATUS_TERMINATED, // the thread is about to exit
	};
	struct ThreadContext
	{
		Event quit;
		ThreadStatus status;
		Thread* ptr_thread;
	};
	typedef std::list<ThreadContext*> worker_list;
	typedef worker_list::iterator worker_iter;

public:
	ThreadPool(const char* name_=0);
	virtual ~ThreadPool();

public:
	virtual NEBULA_ERROR_CODE start(
			unsigned int min_thread_count,
			unsigned int max_thread_count);
	virtual NEBULA_ERROR_CODE stop();

	// asynchronously notify the thread pool to stop, you still have
	// to call 'stop' to recycle the resource
	virtual NEBULA_ERROR_CODE notify_to_stop();

	virtual NEBULA_ERROR_CODE set_thread_count_range(
			unsigned int min_thread_count,
			unsigned int max_thread_count);

	virtual NEBULA_ERROR_CODE set_maintain_interval(
			unsigned int milliseconds);

protected:
	virtual void worker(ThreadContext* context) = 0;

	void vigilant_sleep(unsigned int milliseconds);

private:
	void regulator();

	NEBULA_ERROR_CODE create_regulator();
	NEBULA_ERROR_CODE join_regulator();

	NEBULA_ERROR_CODE add_workers(unsigned int add_count);
	NEBULA_ERROR_CODE reduce_workers(unsigned int reduce_count);

private:
	std::string name;
	Event shutdown;

	Mutex lock;

	unsigned int min_worker_count;
	unsigned int max_worker_count;
	unsigned int thr_maintain_interval_millisecs;

	ThreadContext* m_regulator;
	worker_list m_workers;
};

}} // namespace nebula::utility

#endif

